/*********************
* Author:Dzlua
* QQ:505544956
* time:2016/08/11
*/
#include "String.h"
#include "Log.h"

#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>

EDUI_NAMESPACE_BEGIN

#ifndef _WIN32
#define stricmp strcasecmp 
char *strupr(char *str) 
{ 
	char *ptr = str; 

	while (*ptr != '\0') { 
		if (islower(*ptr)) 
		*ptr = toupper(*ptr); 
		ptr++; 
	} 

	return str; 
}

char *strlwr(char *str) 
{ 
	char *ptr = str; 

	while (*ptr != '\0') { 
		if (isupper(*ptr)) 
		*ptr = tolower(*ptr); 
		ptr++; 
	} 

	return str; 
}

wchar_t *wcsupr(wchar_t *str) 
{ 
	wchar_t *ptr = str; 

	while (*ptr != '\0') { 
		if (islower(*ptr)) 
		*ptr = toupper(*ptr); 
		ptr++; 
	} 

	return str; 
}

wchar_t *wcslwr(wchar_t *str) 
{ 
	wchar_t *ptr = str; 

	while (*ptr != '\0') { 
		if (isupper(*ptr)) 
		*ptr = tolower(*ptr); 
		ptr++; 
	} 

	return str; 
}


#else
#define vsnprintf _vsnprintf_c
#define stricmp _stricmp
#define strupr  _strupr
#define strlwr  _strlwr
#endif

String::String() : m_pstr(m_szBuffer)
{
    m_szBuffer[0] = '\0';
}

String::String(const char ch) : m_pstr(m_szBuffer)
{
    m_szBuffer[0] = ch;
    m_szBuffer[1] = '\0';
}

String::String(const char* lpsz, int nLen) : m_pstr(m_szBuffer)
{      
    if(lpsz)
    {
        m_szBuffer[0] = '\0';
        Assign(lpsz, nLen);
    }
    else
    {
        if (m_pstr!=m_szBuffer)
        {
            free(m_pstr);
        }
        m_szBuffer[0] = '\0';
    }
}

String::String(const String& src) : m_pstr(m_szBuffer)
{
    m_szBuffer[0] = '\0';
    Assign(src.m_pstr);
}

String::~String()
{
    if( m_pstr != m_szBuffer ) free(m_pstr);
}

int String::GetLength() const
{
    const char* ptr=m_pstr;
    while(*ptr)
    {
        ++ptr;
    }
    return int(ptr-m_pstr); 
}

String::operator const char*() const 
{ 
    return m_pstr; 
}

void String::Append(const char* pstr)
{
    int nNewLength = GetLength() + (int) strlen(pstr);
    if( nNewLength >= MAX_LOCAL_STRING_LEN ) {
        if( m_pstr == m_szBuffer ) {
            m_pstr = static_cast<char*>(malloc((nNewLength + 1) * sizeof(char)));
            strcpy(m_pstr, m_szBuffer);
            strcat(m_pstr, pstr);
        }
        else {
            m_pstr = static_cast<char*>(realloc(m_pstr, (nNewLength + 1) * sizeof(char)));
            strcat(m_pstr, pstr);
        }
    }
    else {
        if( m_pstr != m_szBuffer ) {
            free(m_pstr);
            m_pstr = m_szBuffer;
        }
        strcat(m_szBuffer, pstr);
    }
}

void String::Assign(const char* pstr, int cchMax)
{
    if( pstr == NULL ) pstr = "";
    cchMax = (cchMax < 0 ? (int) strlen(pstr) : cchMax);
    if( cchMax < MAX_LOCAL_STRING_LEN ) {
        if( m_pstr != m_szBuffer ) {
            free(m_pstr);
            m_pstr = m_szBuffer;
        }
    }
    else if( cchMax > GetLength() || m_pstr == m_szBuffer ) {
        if( m_pstr == m_szBuffer ) m_pstr = NULL;
        m_pstr = static_cast<char*>(realloc(m_pstr, (cchMax + 1) * sizeof(char)));
    }
    strncpy(m_pstr, pstr, cchMax);
    m_pstr[cchMax] = '\0';
}

//重新分配大小
void String::Resize(int length)
{
    if (length<MAX_LOCAL_STRING_LEN)
    {
        if( m_pstr != m_szBuffer ) {
            strncpy(m_szBuffer, m_pstr, length);
            free(m_pstr);
            m_pstr = m_szBuffer;
        }
    }
    else
    {
        if(m_szBuffer!=m_pstr)
            m_pstr = static_cast<char*>(realloc(m_pstr, (length + 1) * sizeof(char)));
        else
        {
            m_pstr=static_cast<char*>(malloc((length + 1) * sizeof(char)));
            strcpy(m_pstr,m_szBuffer);
        }
    }
}


bool String::IsEmpty() const 
{ 
    return m_pstr[0] == '\0'; 
}

void String::Empty() 
{ 
    if( m_pstr != m_szBuffer ) free(m_pstr);
    m_pstr = m_szBuffer;
    m_szBuffer[0] = '\0'; 
}

const char* String::GetString() const
{
    return m_pstr;
}

char* String::GetData()
{
    return m_pstr;
}

char String::GetAt(int nIndex) const
{
    return m_pstr[nIndex];
}

char String::operator[] (int nIndex) const
{ 
    return m_pstr[nIndex];
}   

const String& String::operator=(const String& src)
{      
    Assign(src);
    return *this;
}

const String& String::operator=(const char* lpStr)
{      
    if (lpStr)
    {
        Assign(lpStr);
    }
    else
    {
        Empty();
    }
    return *this;
}


const String& String::operator=(const char ch)
{
    Empty();
    m_szBuffer[0] = ch;
    m_szBuffer[1] = '\0';
    return *this;
}

String String::operator+(const String& src) const
{
    String sTemp = *this;
    sTemp.Append(src);
    return sTemp;
}

String String::operator+(const char* lpStr) const
{
    if ( lpStr )
    {
        String sTemp = *this;
        sTemp.Append(lpStr);
        return sTemp;
    }

    return *this;
}

const String& String::operator+=(const String& src)
{      
    Append(src);
    return *this;
}

const String& String::operator+=(const char* lpStr)
{      
    if ( lpStr )
    {
        Append(lpStr);
    }
    
    return *this;
}

const String& String::operator+=(const char ch)
{      
    char str[] = { ch, '\0' };
    Append(str);
    return *this;
}

bool String::operator == (const char* str) const { return (Compare(str) == 0); };
bool String::operator != (const char* str) const { return (Compare(str) != 0); };
bool String::operator <= (const char* str) const { return (Compare(str) <= 0); };
bool String::operator <  (const char* str) const { return (Compare(str) <  0); };
bool String::operator >= (const char* str) const { return (Compare(str) >= 0); };
bool String::operator >  (const char* str) const { return (Compare(str) >  0); };

void String::SetAt(int nIndex, char ch)
{
    Assert(nIndex>=0 && nIndex<GetLength());
    m_pstr[nIndex] = ch;
}

int String::Compare(const char* lpsz) const 
{ 
    return strcmp(m_pstr, lpsz); 
}

int String::CompareNoCase(const char* lpsz) const 
{ 
    return stricmp(m_pstr, lpsz); 
}

void String::MakeUpper() 
{ 
    strupr(m_pstr); 
}

void String::MakeLower() 
{ 
    strlwr(m_pstr); 
}

String String::Left(int iLength) const
{
    if( iLength < 0 ) iLength = 0;
    if( iLength > GetLength() ) iLength = GetLength();
    return String(m_pstr, iLength);
}

String String::Mid(int iPos, int iLength) const
{
    if( iLength < 0 ) iLength = GetLength() - iPos;
    if( iPos + iLength > GetLength() ) iLength = GetLength() - iPos;
    if( iLength <= 0 ) return String();
    return String(m_pstr + iPos, iLength);
}

String String::Right(int iLength) const
{
    int iPos = GetLength() - iLength;
    if( iPos < 0 ) {
        iPos = 0;
        iLength = GetLength();
    }
    return String(m_pstr + iPos, iLength);
}

int String::Find(char ch, int iPos /*= 0*/) const
{
    Assert(iPos>=0 && iPos<=GetLength());
    if( iPos != 0 && (iPos < 0 || iPos >= GetLength()) ) return -1;
    const char* p = strchr(m_pstr + iPos, ch);
    if( p == NULL ) return -1;
    return (int)(p - m_pstr);
}

int String::Find(const char* pstrSub, int iPos /*= 0*/) const
{
    Assert(iPos>=0 && iPos<=GetLength());
    if( iPos != 0 && (iPos < 0 || iPos > GetLength()) ) return -1;
    const char* p = strstr(m_pstr + iPos, pstrSub);
    if( p == NULL ) return -1;
    return (int)(p - m_pstr);
}

int String::ReverseFind(char ch) const
{
    const char* p = strrchr(m_pstr, ch);
    if( p == NULL ) return -1;
    return (int)(p - m_pstr);
}

int String::Replace(const char* pstrFrom, const char* pstrTo)
{
    String sTemp;
    int nCount = 0;
    int iPos = Find(pstrFrom);
    if( iPos < 0 ) return 0;
    int cchFrom = (int) strlen(pstrFrom);
    int cchTo = (int) strlen(pstrTo);
    while( iPos >= 0 ) {
        sTemp = Left(iPos);
        sTemp += pstrTo;
        sTemp += Mid(iPos + cchFrom);
        Assign(sTemp);
        iPos = Find(pstrFrom, iPos + cchTo);
        nCount++;
    }
    return nCount;
}

void String::Replace(const char* pstrTo, int pos,int len)
{
    if (len > 0) Remove(pos, len);
    String b = Left(pos);
    String e = Right(GetLength() - pos);
    *this = b + pstrTo + e;
}

int String::Format(const char* pstrFormat, va_list Args)
{
    int totalLen = (1024)*sizeof(char);
    char* szBuffer = (char*)malloc(totalLen);
    memset(szBuffer,0,totalLen);
    int nLen = vsnprintf(szBuffer, totalLen, pstrFormat, Args);
    Assign(szBuffer);
    free(szBuffer);
    return nLen;
}

int String::Format(const char* pstrFormat, ...)
{
    int nRet;
    va_list Args;

    va_start(Args, pstrFormat);
    nRet = Format(pstrFormat, Args);
    va_end(Args);

    return nRet;

}

int String::SmallFormat(const char* pstrFormat, ...)
{
    String sFormat = pstrFormat;
    char szBuffer[64] = { 0 };
    va_list argList;
    va_start(argList, pstrFormat);
    int iRet = vsnprintf(szBuffer, sizeof(szBuffer), sFormat, argList);
    va_end(argList);
    Assign(szBuffer);
    return iRet;
}


bool String::Remove(int pos,int len)
{
    int left=0,right=0;
    if (len>0)
    {
        left=pos;
        right=pos+len;
    }
    else
    {
        left=pos+len;
        right=pos;
    }
    if (left<0)
    {
        return false;
    }

    int textlen=GetLength();
    if (right>textlen)
    {
        return false;
    }

    for (int pos=right;pos<=textlen;++pos)
    {
        m_pstr[left+pos-right]=m_pstr[pos];
    }
    return true;
}

EDUI_NAMESPACE_END
